<?php

namespace app\admin\model;


class Picture extends Common
{
    protected $dateFormat = 'Y-m-d H:i:S';
    protected $type = [
        'create_time' => 'timestamp',
        'update_time' => 'timestamp',
    ];
    protected $autoWriteTimestamp = true;

    /**
     * 文件上传
     * @param file   $file 图片文件
     * @param array  $setting 文件上传配置
     * @param string $path_key 返回图片路径的下标
     * @return bool
     * @throws \Exception
     */
    public function upload($file, $setting, $path_key = 'path')
    {
        /* 上传文件 */
        $fileObj = request()->file(array_keys($file)[0]);
        if (!empty($fileObj)) {
            /** 判断是不是多张图片 */
            if (is_array($file[array_keys($file)[0]]['name'])) {
                $id = [];
                //多图 移动图片至本地目录
                foreach ($fileObj as $key => $file) {
                    $hash['md5'] = $file->hash('md5');
                    $hash['sha1'] = $file->hash('sha1');
                    $is_have = $this->isFile($hash);
                    if ($is_have) {
                        $id[] = $is_have;
                    } else {
                        $infoObj = $file->validate(['size' => $setting['size'], 'ext' => $setting['ext']])->rule($setting['rule'])->move($setting['rootPath'], true, $setting['replace']);
                        if ($infoObj) {
                            $this->data = [
                                'path' => "/uploads/Picture/" . str_replace('\\', '/', $infoObj->getSaveName()),
                                'md5' => $hash['md5'],
                                'sha1' => $hash['sha1'],
                            ];
                            $this->save();
                            $id[] = $this->id;

                        } else {
                            $this->error = $file->getError();
                            return false;
                        }
                    }
                }
                $id = implode(",", $id);

                $info = [];
                $ids = explode(",", $id);
                foreach ($ids as $key => &$value) {
                    $info[] = $this->field("id,path " . $path_key)->where(["id" => $value])->find();
                }
            } else {
                $hash['md5'] = $fileObj->hash('md5');
                $hash['sha1'] = $fileObj->hash('sha1');

                $is_have = $this->isFile($hash);
                if ($is_have) {
                    $id = $is_have;
                } else {
                    $infoObj = $fileObj->validate(['size' => $setting['size'], 'ext' => $setting['ext']])->rule($setting['rule'])->move($setting['rootPath'], true, $setting['replace']);
                    if ($infoObj) {
                        $this->data = [
                            'path' => "/uploads/Picture/" . str_replace('\\', '/', $infoObj->getSaveName()),
                            'md5' => $hash['md5'],
                            'sha1' => $hash['sha1'],
                        ];

                        $this->save();
                        $id = $this->id;
                    } else {
                        $this->error = $fileObj->getError();
                        return false;
                    }
                }

                $info = $this->field("id,path " . $path_key)->where(["id" => $id])->find();
            }

            return $info; //文件上传成功
        } else {
            $this->error = '没有文件上传';
            return false;
        }

    }

    /**
     * 下载指定文件
     * @param number  $root 文件存储根目录
     * @param integer $id 文件ID
     * @param string  $args 回调函数参数
     * @return boolean       false-下载失败，否则输出下载文件
     */
    public function download($root, $id, $callback = null, $args = null)
    {
        /* 获取下载文件信息 */
        $file = $this->find($id);
        if (!$file) {
            $this->error = '不存在该文件！';
            return false;
        }

        /* 下载文件 */
        switch ($file['location']) {
            case 0: //下载本地文件
                $file['rootpath'] = $root;
                return $this->downLocalFile($file, $callback, $args);
            case 1: //下载FTP文件
                $file['rootpath'] = $root;
                return $this->downFtpFile($file, $callback, $args);
                break;
            default:
                $this->error = '不支持的文件存储类型！';
                return false;

        }

    }

    /**
     * 检测当前上传的文件是否已经存在
     * @param array $file 文件上传数组
     * @return boolean       文件信息， false - 不存在该文件
     * @throws Exception
     */
    public function isFile($file)
    {
        if (empty($file['md5'])) {
            throw new Exception('缺少参数:md5');
        }
        /* 查找文件 */
        $map = array('md5' => $file['md5'], 'sha1' => $file['sha1'],);
        return $this->field(true)->where($map)->value("id");
    }

    /**
     * 下载本地文件
     * @param array    $file 文件信息数组
     * @param callable $callback 下载回调函数，一般用于增加下载次数
     * @param string   $args 回调函数参数
     * @return boolean            下载失败返回false
     */
    private function downLocalFile($file, $callback = null, $args = null)
    {
        if (is_file($file['rootpath'] . $file['savepath'] . $file['savename'])) {
            /* 调用回调函数新增下载数 */
            is_callable($callback) && call_user_func($callback, $args);

            /* 执行下载 */ //TODO: 大文件断点续传
            header("Content-Description: File Transfer");
            header('Content-type: ' . $file['type']);
            header('Content-Length:' . $file['size']);
            if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) { //for IE
                header('Content-Disposition: attachment; filename="' . rawurlencode($file['name']) . '"');
            } else {
                header('Content-Disposition: attachment; filename="' . $file['name'] . '"');
            }
            readfile($file['rootpath'] . $file['savepath'] . $file['savename']);
            exit;
        } else {
            $this->error = '文件已被删除！';
            return false;
        }
    }

    /**
     * 下载ftp文件
     * @param array    $file 文件信息数组
     * @param callable $callback 下载回调函数，一般用于增加下载次数
     * @param string   $args 回调函数参数
     * @return boolean            下载失败返回false
     */
    private function downFtpFile($file, $callback = null, $args = null)
    {
        /* 调用回调函数新增下载数 */
        is_callable($callback) && call_user_func($callback, $args);

        $host = C('DOWNLOAD_HOST.host');
        $root = explode('/', $file['rootpath']);
        $file['savepath'] = $root[3] . '/' . $file['savepath'];

        $data = array($file['savepath'], $file['savename'], $file['name'], $file['mime']);
        $data = json($data);
        $key = thinkEncrypt($data, C('DATA_AUTH_KEY'), 600);

        header("Location:http://{$host}/onethink.php?key={$key}");
    }

    /**
     * 获取最后一次上传错误信息
     * @return string 错误信息
     */
    public function getError()
    {
        return $this->error;
    }
}